package com.lambda.swipeback;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;

public class SwipeBackLayout extends FrameLayout {
    public WxViewDragHelper mDragHelper;
    private float mSwipePercent;
    public Drawable mShadowDrawable;
    private boolean mNeedRequestActivityTranslucent;
    private boolean mRequestedTranslucent;
    public boolean mActivityTranslucentCompleted;
    public boolean FQG;
    public boolean mSwiping;
    private boolean mFastRelease;
    private OnTouchListener mTouchListener;
    private Drawable mDecorBackground;
    private boolean mOnceDisEnableGesture;
    private boolean mNeedChangeWindowBackground;
    public SwipeGestureDelegate mGestureDelegate;
    private float mSwipeBackPercent;
    private int mScrollLeft;
    private int mScrollTop;
    private float mShadowAlpha;
    private Rect mRect;
    public View mContentView; // self/this or child
    private boolean mEnable;
    private boolean mInLayout;

    public interface SwipeGestureDelegate {
        void onCancel();

        void onDrag();

        void onSwipeBack();
    }

    public interface OnTouchListener {
        void aL(float f);

        int bt(boolean z);

        void onTouchEvent(MotionEvent motionEvent);
    }

    private class DragCallback extends WxViewDragHelper.Callback implements ActivityUtil.TranslucentConversionListener {
        int clampPosition = 0;
        int releaseLeft = 0;

        @Override
        public int clampViewPositionHorizontal(View view, int left) {
            if (mActivityTranslucentCompleted) {
                int max = Math.max(clampPosition, left);
                clampPosition = 0;
                return Math.min(view.getWidth(), Math.max(max, 0));
            }
            clampPosition = Math.max(clampPosition, left);
            return 0;
        }

        @Override
        public void onViewReleased(View view, float xvel, float yvel) {
            releaseLeft = (xvel > 0.0f || (xvel == 0.0f && mSwipePercent > mSwipeBackPercent)) ? (view.getWidth() + mShadowDrawable.getIntrinsicWidth()) + 10 : 0;
            ad.i("MicroMsg.SwipeBackLayout", "ashutest::onViewReleased, xvel:%f yvel:%f, releaseLeft:%d, releaseTop:%d, translucent %B", xvel, yvel, releaseLeft, 0, mActivityTranslucentCompleted);
            mSwiping = true;
            if (mTouchListener != null) {
                int state = mTouchListener.bt(releaseLeft != 0);
                ad.i("MicroMsg.SwipeBackLayout", "intercepted by mSwipeBackListener.onViewReleased, result:%s", state);
                if (state == 2) {
                    releaseLeft = 0;
                } else if (state == 3) {
                    return;
                }
            }
            if (mActivityTranslucentCompleted) {
                if (!mDragHelper.mReleaseInProgress)
                    throw new IllegalStateException("Cannot settleCapturedViewAt outside of a call to Callback#onViewReleased");

                int velx = (int) mDragHelper.mVelocityTracker.getXVelocity(mDragHelper.mActivePointerId);
                int vely = (int) mDragHelper.mVelocityTracker.getYVelocity(mDragHelper.mActivePointerId);
                mDragHelper.forceSettleCapturedViewAt(releaseLeft, 0, velx, vely, 0);
                invalidate();
                return;
            }
            mFastRelease = true;
        }

        @Override
        public final void onViewDragStateChanged(int state) {
            ad.i("MicroMsg.SwipeBackLayout", "ashutest::onViewDragStateChanged state %d, requestedTranslucent %B fastRelease %B", state, mRequestedTranslucent, mFastRelease);
            if (WxViewDragHelper.STATE_DRAGGING == state) {
                ad.i("MicroMsg.SwipeBackLayout", "ashutest:: on drag");
                if ((getContext() instanceof Activity) && mDecorBackground == null) {
                    mDecorBackground = ((Activity) getContext()).getWindow().getDecorView().getBackground();
                    if (mNeedChangeWindowBackground) {
                        ((Activity) getContext()).getWindow().getDecorView().setBackgroundResource(R.color.a_q);
                    }
                }
                if (mGestureDelegate != null) {
                    mGestureDelegate.onDrag();
                }
                FQG = false;
                if (mActivityTranslucentCompleted) {
                    SwipeBackHelper.notifySwipe(0.0f);
                }
            }
            if (state == WxViewDragHelper.STATE_IDLE && !mFastRelease) {
                ad.i("MicroMsg.SwipeBackLayout", "ashutest:: on cancel");
                if (mGestureDelegate != null) {
                    if ((getContext() instanceof Activity) && mDecorBackground != null) {
                        if (mNeedChangeWindowBackground) {
                            ((Activity) getContext()).getWindow().getDecorView().setBackground(mDecorBackground);
                        }
                        mDecorBackground = null;
                    }
                    mGestureDelegate.onCancel();
                }
                SwipeBackHelper.notifySwipe(1.0f);
            }
            if (WxViewDragHelper.STATE_DRAGGING == state &&
                    mNeedRequestActivityTranslucent &&
                    (getContext() instanceof Activity) &&
                    !mActivityTranslucentCompleted &&
                    !mRequestedTranslucent) {
                ad.i("MicroMsg.SwipeBackLayout", "ashutest:: match dragging");
                mRequestedTranslucent = true;
                ActivityUtil.convertToTranslucent((Activity) getContext(), this);
            }
            if (WxViewDragHelper.STATE_SETTLING == state) {
                ad.i("MicroMsg.SwipeBackLayout", "ashutest:: notify settle, mReleasedLeft %d", releaseLeft);
                SwipeBackHelper.notifySettle(releaseLeft > 0, releaseLeft);
            }
        }

        @Override
        public void onTranslucentConversionComplete(final boolean complete) {
            ToolsAQ.f(new Runnable() {
                public final void run() {
                    mRequestedTranslucent = complete;
                    if (releaseLeft > 0) {
                        SwipeBackHelper.notifySwipe(0);
                    } else {
                        SwipeBackHelper.notifySwipe(1.0f);
                    }
                    setTranslucentConversionCompleted(complete);
                    mFastRelease = false;
                }
            });
        }

        @Override
        public void onViewPositionChanged(int left, int top) {
            if (mActivityTranslucentCompleted) {
                mSwipePercent = Math.abs(((float) left) / ((float) (mContentView.getWidth() + mShadowDrawable.getIntrinsicWidth())));
                mScrollLeft = left;
                mScrollTop = top;
                invalidate();
                if (mTouchListener != null) {
                    mTouchListener.aL(mSwipePercent);
                }
                if (Float.compare(mSwipePercent, 1.0f) >= 0 && !FQG) {
                    FQG = true;
                    ToolsAQ.f(new Runnable() {
                        public final void run() {
                            if (mGestureDelegate != null) {
                                if ((getContext() instanceof Activity) && mDecorBackground != null) {
                                    if (mNeedChangeWindowBackground) {
                                        ((Activity) getContext()).getWindow().getDecorView().setBackground(mDecorBackground);
                                    }
                                    mDecorBackground = null;
                                }
                                mGestureDelegate.onSwipeBack();
                            }
                            mSwiping = false;
                        }
                    });
                } else if (Float.compare(mSwipePercent, 0.01f) <= 0) {
                    mSwiping = false;
                }
                if (mDragHelper.mState == WxViewDragHelper.STATE_DRAGGING) {
                    SwipeBackHelper.notifySwipe(mSwipePercent);
                }
            }
        }

        @Override
        public boolean tryCaptureView(int pointerId) {
            return (mDragHelper.mPointersDown & (1 << pointerId)) != 0 && (mDragHelper.mInitialEdgesTouched[pointerId] & 1) != 0;
        }

        @Override
        public final int getViewHorizontalDragRange() {
            return 1;
        }
    }

    public SwipeBackLayout(@NonNull Context context) {
        this(context, null);
    }

    public SwipeBackLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SwipeBackLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        this.mSwipeBackPercent = 0.3f;
        this.mEnable = true;
        this.mRect = new Rect();
        this.mNeedRequestActivityTranslucent = true;
        this.mRequestedTranslucent = false;
        this.mActivityTranslucentCompleted = false;
        this.FQG = false;
        this.mSwiping = false;
        this.mFastRelease = false;
        this.mNeedChangeWindowBackground = true;
        this.mGestureDelegate = null;
        this.mShadowDrawable = getResources().getDrawable(R.drawable.shadow);
        setFocusable(true);
        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
        init();
    }

    public void init() {
        this.mDragHelper = WxViewDragHelper.create(this, new DragCallback(), AnimationUtils.loadInterpolator(getContext(), R.anim.c0));
        this.mDragHelper.mTrackingEdges = 1;
        float f = getResources().getDisplayMetrics().density;
        this.mDragHelper.mMinVelocity = 100.0f * f;
        this.mDragHelper.mMaxVelocity = 300.0f * f;
        this.mScrollLeft = 0;
        this.mScrollTop = 0;
    }

    public final void setTranslucentConversionCompleted(boolean completed) {
        this.mActivityTranslucentCompleted = completed;
    }

    public void setNeedRequestActivityTranslucent(boolean request) {
        mNeedRequestActivityTranslucent = request;
        if (mNeedRequestActivityTranslucent) {
            mRequestedTranslucent = false;
        }
    }

    public void setSwipeBackListener(OnTouchListener listener) {
        mTouchListener = listener;
    }


    public void setContentView(View view) {
        this.mContentView = view;
    }

    public View getTargetContentView() {
        return this.mContentView;
    }

    @Override
    public void onFinishInflate() {
        super.onFinishInflate();
        mContentView = this;
    }

    public void setEnableGesture(boolean z) {
        mEnable = z;
    }

    public void setOnceDisEnableGesture(boolean z) {
        mOnceDisEnableGesture = z;
    }
    public final boolean swipeBack() {
        isSwiping();
        return mSwiping;
    }

    public final boolean isSwiping() {
        if (!mSwiping) {
            return false;
        }

        if (Float.compare(mContentView.getLeft(), 0.01f) <= 0) {
            mSwiping = false;
            return false;
        } else {
            return true;
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent motion) {
        if (!mEnable) return super.dispatchTouchEvent(motion);
        if (mTouchListener != null) mTouchListener.onTouchEvent(motion);
        if (motion.getAction() == MotionEvent.ACTION_DOWN) mOnceDisEnableGesture = false;
        if (mOnceDisEnableGesture) return super.dispatchTouchEvent(motion);
        if (isSwiping()) return super.dispatchTouchEvent(motion);

        int masked;
        int index;
        float x;
        float y;
        View topChild;
        int pointerId;
        int pointerCount;

        masked = motion.getActionMasked();
        index = motion.getActionIndex();
        if (mDragHelper.mState == WxViewDragHelper.STATE_DRAGGING) {
            if (masked == MotionEvent.ACTION_DOWN) {
                mDragHelper.cancel();
            }
            if (mDragHelper.mVelocityTracker == null) {
                mDragHelper.mVelocityTracker = VelocityTracker.obtain();
            }
            mDragHelper.mVelocityTracker.addMovement(motion);
            switch (masked) {
                case MotionEvent.ACTION_DOWN:
                    x = motion.getX();
                    y = motion.getY();

                    pointerId = motion.getPointerId(index);
                    mDragHelper.saveInitialMotion(x, y, pointerId);

                    topChild = mDragHelper.findTopChildUnder((int) x, (int) y);
                    mDragHelper.tryCaptureViewForDrag(topChild, pointerId);
                    break;
                case MotionEvent.ACTION_UP:
                    if (mDragHelper.mState == WxViewDragHelper.STATE_DRAGGING) {
                        mDragHelper.releaseViewForPointerUp();
                    }
                    mDragHelper.cancel();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mDragHelper.mState == WxViewDragHelper.STATE_DRAGGING) {
                        int pointerIndex = motion.findPointerIndex(mDragHelper.mActivePointerId);

                        int dx = (int) (motion.getX(pointerIndex) - mDragHelper.mLastMotionX[mDragHelper.mActivePointerId]);
                        int dy = (int) (motion.getY(pointerIndex) - mDragHelper.mLastMotionY[mDragHelper.mActivePointerId]);

                        int newLeft = mDragHelper.mCapturedView.getLeft() + dx;
                        int newTop = mDragHelper.mCapturedView.getTop() + dy;
                        int currentLeft = mDragHelper.mCapturedView.getLeft();
                        int currentTop = mDragHelper.mCapturedView.getTop();

                        if (dx != 0) {
                            newLeft = mDragHelper.mCallback.clampViewPositionHorizontal(mDragHelper.mCapturedView, newLeft);
                            mDragHelper.mCapturedView.offsetLeftAndRight(newLeft - currentLeft);
                        }

                        if (dy != 0) {
                            mDragHelper.mCapturedView.offsetTopAndBottom(0 - currentTop);
                            newTop = 0;
                        }

                        if (!(dx == 0 && dy == 0)) {
                            mDragHelper.mCallback.onViewPositionChanged(newLeft, newTop);
                        }
                        mDragHelper.saveLastMotion(motion);
                    } else {
                        pointerCount = motion.getPointerCount();
                        for (int i = 0; i < pointerCount; i += 1) {
                            index = motion.getPointerId(i);
                            x = motion.getX(index);
                            y = motion.getY(index);
                            float dx = x - mDragHelper.mInitialMotionX[index];
                            float dy = y - mDragHelper.mInitialMotionY[index];
                            mDragHelper.reportNewEdgeDrags(dx, dy, index);
                            if (mDragHelper.mState != WxViewDragHelper.STATE_DRAGGING) {
                                topChild = mDragHelper.findTopChildUnder((int) x, (int) y);
                                if (!mDragHelper.checkTouchSlop(topChild, dx) || !mDragHelper.tryCaptureViewForDrag(topChild, index)) {
                                    continue;
                                }
                            }
                            mDragHelper.saveLastMotion(motion);
                            break;
                        }
                        mDragHelper.saveLastMotion(motion);
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                    if (mDragHelper.mState == WxViewDragHelper.STATE_DRAGGING) {
                        mDragHelper.dispatchViewReleased(0.0f, 0.0f);
                    }
                    mDragHelper.cancel();
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    pointerId = motion.getPointerId(index);
                    x = motion.getX(index);
                    y = motion.getY(index);
                    mDragHelper.saveInitialMotion(x, y, pointerId);
                    if (mDragHelper.mState != WxViewDragHelper.STATE_IDLE) {
                        if (mDragHelper.mCapturedView != null
                                && x >= mDragHelper.mCapturedView.getLeft()
                                && x < mDragHelper.mCapturedView.getRight()
                                && y >= mDragHelper.mCapturedView.getTop()
                                && y < mDragHelper.mCapturedView.getBottom()
                        ) {
                            mDragHelper.tryCaptureViewForDrag(mDragHelper.mCapturedView, pointerId);
                        }
                    } else {
                        topChild = mDragHelper.findTopChildUnder((int) x, (int) y);
                        mDragHelper.tryCaptureViewForDrag(topChild, pointerId);
                    }
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    pointerId = motion.getPointerId(index);
                    mDragHelper.clearMotionHistory(pointerId);
                    if (mDragHelper.mState == WxViewDragHelper.STATE_DRAGGING && pointerId == mDragHelper.mActivePointerId) {
                        pointerCount = motion.getPointerCount();
                        for (int i = 0; i < pointerCount; i += 1) {
                            pointerId = motion.getPointerId(i);
                            if (pointerId != mDragHelper.mActivePointerId) {
                                topChild = mDragHelper.findTopChildUnder((int) motion.getX(i), (int) motion.getY(i));
                                if (topChild == mDragHelper.mCapturedView && mDragHelper.tryCaptureViewForDrag(mDragHelper.mCapturedView, pointerId)) {
                                    if (mDragHelper.mActivePointerId == -1) {
                                        mDragHelper.releaseViewForPointerUp();
                                    }
                                }
                            }
                        }
                    }
                    break;
            }
        } else {
            if (masked == MotionEvent.ACTION_DOWN) {
                mDragHelper.cancel();
            }
            if (mDragHelper.mVelocityTracker == null) {
                mDragHelper.mVelocityTracker = VelocityTracker.obtain();
            }
            mDragHelper.mVelocityTracker.addMovement(motion);
            switch (masked) {
                case MotionEvent.ACTION_DOWN:
                    x = motion.getX();
                    y = motion.getY();

                    index = motion.getPointerId(0);
                    mDragHelper.saveInitialMotion(x, y, index);

                    topChild = mDragHelper.findTopChildUnder((int) x, (int) y);
                    mDragHelper.tryCaptureViewForDrag(topChild, index);
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    mDragHelper.cancel();
                    break;
                case MotionEvent.ACTION_MOVE:
                    pointerCount = motion.getPointerCount();
                    for (int i = 0; i < pointerCount; i += 1) {
                        index = motion.getPointerId(i);
                        x = motion.getX(index);
                        y = motion.getY(index);
                        float dx = x - mDragHelper.mInitialMotionX[index];
                        float dy = y - mDragHelper.mInitialMotionY[index];
                        mDragHelper.reportNewEdgeDrags(dx, dy, index);
                        if (mDragHelper.mState != WxViewDragHelper.STATE_DRAGGING) {
                            topChild = mDragHelper.findTopChildUnder((int) x, (int) y);
                            if (!mDragHelper.checkTouchSlop(topChild, dx) || !mDragHelper.tryCaptureViewForDrag(topChild, index)) {
                                continue;
                            }
                        }
                        mDragHelper.saveLastMotion(motion);
                        break;
                    }
                    mDragHelper.saveLastMotion(motion);
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    pointerId = motion.getPointerId(index);
                    x = motion.getX(pointerId);
                    y = motion.getY(pointerId);
                    mDragHelper.saveInitialMotion(x, y, masked);
                    if (mDragHelper.mState == WxViewDragHelper.STATE_SETTLING) {
                        topChild = mDragHelper.findTopChildUnder((int) x, (int) y);
                        if (topChild == mDragHelper.mCapturedView) {
                            mDragHelper.tryCaptureViewForDrag(topChild, masked);
                        }
                    }
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    pointerId = motion.getPointerId(index);
                    mDragHelper.clearMotionHistory(pointerId);
                    break;
            }
            if (mDragHelper.mState == WxViewDragHelper.STATE_DRAGGING) {
                motion.setAction(MotionEvent.ACTION_CANCEL);
                super.dispatchTouchEvent(motion);
            } else {
                super.dispatchTouchEvent(motion);
            }
        }
        return true;
    }

    protected void onLayout(boolean z, int i, int i2, int i3, int i4) {
        mInLayout = true;
        if (mContentView != null) {
            mContentView.layout(mScrollLeft, mScrollTop, mScrollLeft + mContentView.getMeasuredWidth(), mScrollTop + mContentView.getMeasuredHeight());
        }
        mInLayout = false;
    }

    public void requestLayout() {
        if (!mInLayout) {
            super.requestLayout();
        }
    }

    @Override
    protected boolean drawChild(Canvas canvas, View view, long j) {
        boolean drawChild = super.drawChild(canvas, view, j);
        if (!(Float.compare(mShadowAlpha, 0.0f) <= 0 || mContentView == null || mDragHelper.mState == WxViewDragHelper.STATE_IDLE)) {
            view.getHitRect(mRect);
            mShadowDrawable.setBounds(mRect.left - mShadowDrawable.getIntrinsicWidth(), mRect.top, mRect.left, mRect.bottom);
            mShadowDrawable.setAlpha((int) (mShadowAlpha * 255.0f));
            mShadowDrawable.draw(canvas);
        }
        return drawChild;
    }

    public void computeScroll() {
        mShadowAlpha = Math.max(0.0f, 1.0f - mSwipePercent);
        if (mDragHelper.mState == WxViewDragHelper.STATE_SETTLING) {
            boolean computeScrollOffset = mDragHelper.mScroller.computeScrollOffset();
            int currX = mDragHelper.mScroller.getCurrX();
            int currY = mDragHelper.mScroller.getCurrY();
            int left = currX - mDragHelper.mCapturedView.getLeft();
            int top = currY - mDragHelper.mCapturedView.getTop();
            if (left != 0) {
                mDragHelper.mCapturedView.offsetLeftAndRight(left);
            }
            if (top != 0) {
                mDragHelper.mCapturedView.offsetTopAndBottom(top);
            }
            if (!(left == 0 && top == 0)) {
                mDragHelper.mCallback.onViewPositionChanged(currX, currY);
            }
            if (computeScrollOffset && currX == mDragHelper.mScroller.getFinalX() && currY == mDragHelper.mScroller.getFinalY()) {
                mDragHelper.mScroller.abortAnimation();
                computeScrollOffset = mDragHelper.mScroller.isFinished();
            }
            if (!computeScrollOffset) {
                mDragHelper.mParentView.post(mDragHelper.mSetIdleRunnable);
            }
        }
        if (mDragHelper.mState == WxViewDragHelper.STATE_SETTLING) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }

    public void setNeedChangeWindowBackground(boolean z) {
        mNeedChangeWindowBackground = z;
    }

    public void setSwipeGestureDelegate(SwipeGestureDelegate delegate) {
        mGestureDelegate = delegate;
    }
}
